A race condition is an anomalous behavior due to unexpected critical dependence on the relative timing of events. For example, if one process writes to a shared resource while another process is reading from the same location, then the data read may be the old contents, the new contents, or some mixture of the two depending on the relative timing of the read and write operations. Race conditions also develop when shared resources are accessed by more than one thread of execution, and at least one of the threads modifies the shared resource.
Synchronization mechanisms, such as semaphores, mutexes, task locks, and interrupt locks, control access to the shared resources and allow for mutual exclusion. An interrupt lock guarantees a task exclusive access to the CPU by disabling interrupts, however, it prevents the system from responding to external events for the duration of the lock. Task locks prevent other tasks from preempting the current task, but allow interrupt service requests (ISRs) to issue. However, task locks can lead to unacceptable real time responses, as tasks of higher priority are unable to execute until the locking task leaves the critical region. Semaphores provide for mutual exclusion of data with finer granularity than either interrupt service requests or task locks and coordinate a task's execution with external events. Since the synchronization mechanisms are difficult to implement and a small error in coding can create a race condition, source code should be checked to determine if the synchronization mechanisms have been properly implemented.
Although race conditions can be checked for by manually inspecting the source code, this is a difficult and time consuming task. Moreover, with large amounts of source code manual inspection is not feasible.
Yet another way to check for race conditions is by run-time detection, which analyzes the execution profile of a program. In order to analyze the execution profile of a program, difficult to use instrumentation and/or hardware probes are needed.